package com.ncu.TestOne.Test02;

import com.ncu.TestOne.Test01.config;
import com.ncu.spring.ApplicationContext;
import com.ncu.spring.BeanDefinition;

//编写测试用例
public class Test {
    public static void main(String[] args) {
        //在构造方法时：就会执行Refresh流程
        //本人实现的Refresh流程如下
        /*
          重点讲解对象的获取流程(包括了去缓存中查询，创建对象)
          getBean()方法：先去一级、二级、三级缓存查看是否有当前对象，如果没有就创建对象(Test02会详细阐述)
          创建对象的时候会走创建对象的流程：
            1.创建：
              0.0将当前要创建对象的BeanName放入正在创建对象集合
              1.0首先会选取无参构造，如果没有无参构造，会选择第一个有参构造
              1.1如果使用@Lazy防止构造导致的依赖注入就会创建代理对象
              1.2如果使用工厂对象防止构造导致的依赖注入就会创建工厂对象
              1.3如果上诉都没有就会getBean()得到这个有参构造方法的参数
              1.4将对象放入三级缓存。防止出现set方法导致的依赖注入
            2.依赖注入阶段：
                2.1查看这个类中是否有set方法上方有@Autowried,如果有就根据这个方法的参数名
                   对一级缓存中获取该对象,然后执行该方法实现依赖注入。
                2.2查看这个类中是否有字段上方有@Autowried,如果有就根据这个字段名称去一级
                   缓存中获取该对象，然后调用field.set()对这个字段进行填充
            3.对象初始化：先执行Aware接口的回调 -> 执行 初始化前的后置处理器 -> 执行
                        InitializingBean接口的回调 -> 执行 初始化后的后置处理器(如创建代理)
            4.去二级缓存 earlySingletonObjects 中查看有没有当前 bean
              如果有，说明发生了循环依赖，返回缓存中的 a 对象（可能是代理对象也可能是原始对象，主要看有没有切点匹配到 bean）
            5.将实现了可销毁接口的对象放入可销毁集合
            6.最后结束创建Bean的流程：就是将BeanName从正在创建对象中移除
        */
        ApplicationContext context = new ApplicationContext(config.class);
        //建议您debug调试查看,getBean()流程
        Object o1 = context.getBean("object2");//获取单例对象,存放在单例池中
        Object o4 = context.getBean("objectA");//获取多例对象
    }
}
